package com.smsc.headend.task.engine.executor.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.SystemClock;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.smsc.headend.common.enums.DeviceType;
import com.smsc.headend.common.enums.errorcode.TaskExecuteErrorCode;
import com.smsc.headend.common.utils.RedisUtils;
import com.smsc.headend.module.asset.dmo.ComConfigDMO;
import com.smsc.headend.module.asset.dmo.MeterConfigDMO;
import com.smsc.headend.module.asset.entity.ComEntity;
import com.smsc.headend.module.asset.entity.Meter;
import com.smsc.headend.module.common.entity.DeviceOperation;
import com.smsc.headend.module.data.dmo.DeviceSAPandKeys;
import com.smsc.headend.module.data.dto.AnsiSubDataItemDTO;
import com.smsc.headend.module.data.dto.DLMSSubDataItemDTO;
import com.smsc.headend.module.data.dto.DataItemDTO;
import com.smsc.headend.module.data.enums.DictionaryType;
import com.smsc.headend.module.data.enums.OperationGroup;
import com.smsc.headend.module.data.enums.OperationName;
import com.smsc.headend.module.fwu.entity.LogFwUpgradeHis;
import com.smsc.headend.module.fwu.entity.TemplateFwUpgrade;
import com.smsc.headend.module.protocol.cosem.util.ByteUtils;
import com.smsc.headend.module.report.entity.LogConnectDisConnectHis;
import com.smsc.headend.module.report.entity.LogModeSwitchHisSub;
import com.smsc.headend.module.report.entity.LogScheduleTaskDevice;
import com.smsc.headend.module.task.consts.TaskKafkaTopic;
import com.smsc.headend.module.task.dto.AtomicTask;
import com.smsc.headend.module.task.dto.Task;
import com.smsc.headend.module.task.dto.TaskResult;
import com.smsc.headend.module.task.enums.SubTaskStatus;
import com.smsc.headend.module.task.enums.TaskType;
import com.smsc.headend.module.template.alarmfilter.entity.enums.AlarmFilterEnum;
import com.smsc.headend.task.engine.dao.TaskDAO;
import com.smsc.headend.task.engine.exception.UDISTaskExecutorException;
import com.smsc.headend.task.engine.executor.TaskExecutor;
import com.smsc.headend.task.engine.facade.DataItemFacade;
import com.smsc.headend.task.engine.handler.impl.ReadScalerUnitHandler;
import com.smsc.headend.task.engine.handler.impl.dcuparam.PlcOnlineListHandler;
import com.smsc.headend.task.engine.handler.impl.dcuparam.ReadDcuCollSchemeHandler;
import com.smsc.headend.task.engine.handler.impl.dcuparam.ReadDcuMeterTaskHandler;
import com.smsc.headend.task.engine.handler.impl.dcuparam.ReadDcuSimpleDataHandler;
import com.smsc.headend.task.engine.handler.impl.deviceconfig.*;
import com.smsc.headend.task.engine.handler.impl.firmware.*;
import com.smsc.headend.task.engine.handler.impl.metercontrol.ReadControlModeHandler;
import com.smsc.headend.task.engine.handler.impl.metercontrol.ReadControlStateHandler;
import com.smsc.headend.module.task.dto.AtomicTaskState;
import com.smsc.headend.task.engine.mapper.LogConnectDisConnectHisMapper;
import com.smsc.headend.task.engine.service.ConnectorService;
import com.smsc.headend.task.engine.service.FeignAssetManagementService;
import com.smsc.headend.task.engine.service.asset.AssetService;
import com.smsc.headend.task.engine.service.task.LogScheduleTaskDeviceService;
import com.smsc.headend.task.engine.service.task.TaskPacketService;
import com.smsc.headend.task.engine.utils.StepKeyUtil;
import gurux.dlms.enums.ObjectType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.util.CollectionUtils;

import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;

@Slf4j
public class ReadExecutor implements TaskExecutor {

    @Autowired
    TaskPacketService packetService;
    @Autowired
    ConnectorService connectorService;

    @Autowired
    RedisUtils redisUtils;
    @Autowired
    FeignAssetManagementService assetManagementRemoteService;
    @Autowired
    AssetService assetService;
    @Autowired
    DataItemFacade dataItemFacade;
    @Autowired
    TaskDAO taskDAO;
    @Autowired
    KafkaTemplate kafkaTemplate;
    @Autowired
    LogConnectDisConnectHisMapper logConnectDisConnectHisMapper;
    @Autowired
    LogScheduleTaskDeviceService logScheduleTaskDeviceService;

    @Override
    public AtomicTaskState execute(Task task, AtomicTask atomicTask) throws UDISTaskExecutorException {
        DeviceOperation dictionary = assetService.getDictionary(atomicTask.getOperationId(), DictionaryType.Operation.getType());
        Meter meter = getMeter(task, assetService);
        MeterConfigDMO meterConfigDMO = task.getMeterId() == null ? null : assetService.getMeterConfigById(task.getMeterId());
        ComEntity terminal = assetService.getComById(task.getComId());
        ComConfigDMO comConfigDMO = assetService.getComConfigById(task.getComId());

        readTaskExecutable(task, atomicTask, terminal);

        List<DataItemDTO> dataItemCosemList = dataItemFacade.getDataItemsByOperation(meter, terminal, dictionary, getParameterMap(task, atomicTask), comConfigDMO.getModelId());
        if (CollectionUtils.isEmpty(dataItemCosemList)) {
            throw new UDISTaskExecutorException(TaskExecuteErrorCode.DATAITEM_NOT_EXISTS.toString());
        }
        Boolean isReadFromTerminal = isReadFromTerminal(task, atomicTask);
        DataItemDTO dataItemDto = dataItemCosemList.get(0);
        DeviceSAPandKeys deviceKeys = dataItemDto instanceof AnsiSubDataItemDTO && meter != null ? assetManagementRemoteService.getMeterCommunicationKey(meter.getMeterId(), dataItemDto.getRoleId()) :
                assetManagementRemoteService.getTerminalCommunicationKey(terminal.getComId(), dataItemDto.getRoleId());
        byte[] packets = packetService.buildReadOneAttributePacket(dataItemCosemList.get(0), isReadFromTerminal ? comConfigDMO : meterConfigDMO, deviceKeys);
        if (packets == null) {
            log.error("build packet fail {}", dataItemCosemList.get(0));
            throw new UDISTaskExecutorException(TaskExecuteErrorCode.BUILD_REQUEST_FAIL.toString());
        }
        log.debug(ByteUtils.byteToHexString(packets));
        if (StrUtil.equalsAny(task.getTaskType(), TaskType.Interface_ODR_Data.toString())) {
            // 该task缓存报文
            connectorService.sendPacket(task, atomicTask, dataItemCosemList.get(0).getRoleId(), true, packets);
        } else {
            connectorService.sendPacket(task, atomicTask, dataItemCosemList.get(0).getRoleId(), task.getIsODR(), packets);
        }


        if (task.getTaskType().equals(TaskType.SwitchMeterPayment.toString())) {
            Map<String, Object> parameterMap = getParameterMap(task, atomicTask);
            Long taskId = MapUtil.getLong(parameterMap, "taskId");
            if (atomicTask.getGroupId() == OperationGroup.Disconnect.getId().intValue()) {
                assetManagementRemoteService.updateStepStatus(taskId, task.getMeterId(), LogModeSwitchHisSub.Step.Disconnect, SubTaskStatus.Processing.getCode(), SystemClock.now() / 1000, null, null);
            } else if (atomicTask.getGroupId() == OperationGroup.ConnectArmed.getId().intValue()) {
                assetManagementRemoteService.updateStepStatus(taskId, task.getMeterId(), LogModeSwitchHisSub.Step.Connect, SubTaskStatus.Processing.getCode(), SystemClock.now() / 1000, null, null);
            }
        }

        // 插入拉合闸日志
        boolean flag = (
                task.getTaskType().equals(TaskType.MeterPlanCdc.toString()) ||
                        task.getTaskType().equals(TaskType.UAA_MeterControl.toString()) ||
                        task.getTaskType().equals(TaskType.Action_MeterControl.toString())) &&
                (atomicTask.getGroupId() == OperationGroup.Disconnect.getId().intValue()
                        || atomicTask.getGroupId() == OperationGroup.ConnectArmed.getId().intValue()
                        || atomicTask.getGroupId() == OperationGroup.Connect.getId().intValue());
        if (flag) {
            insertLogConnectDisConnectHis(task, atomicTask, LogConnectDisConnectHis.Result.noAction.getCode(), "");
        }

        Class handlerClass = getHandlerClass(dataItemDto, atomicTask);
        return createAtomicState(handlerClass);
    }

    @Override
    public Boolean handleFailure(Task task, AtomicTask atomicTask, String message) {
        if (task.getTaskType().equals(TaskType.SwitchMeterPayment.toString())) {
            Map<String, Object> parameterMap = getParameterMap(task, atomicTask);
            Long taskId = MapUtil.getLong(parameterMap, "taskId");
            Long now = SystemClock.now() / 1000;
            LogModeSwitchHisSub.Step step = null;
            switch (OperationGroup.forId(atomicTask.getGroupId().intValue())) {
                case Connect:
                case ConnectArmed:
                    step = LogModeSwitchHisSub.Step.Connect;
                    break;
                case Disconnect:
                    step = LogModeSwitchHisSub.Step.Disconnect;
                    break;
            }
            assetManagementRemoteService.updateStepStatus(taskId, task.getMeterId(), step, SubTaskStatus.Failed.getCode(), isSubTaskGroupFirstAtomicTask(task, atomicTask) ? now : null, now,
                    String.format("execute %s fail, [%s]", OperationName.forId(atomicTask.getOperationId()).getName(), message));
        } else {
            String key = "message";
            if (atomicTask.getGroupId() == OperationGroup.ReadRegister.getId().intValue()) {
                Map<String, Object> m = JSONUtil.toBean(atomicTask.getAtomicTaskParam(), Map.class);
                key = m.get("dataItemId") != null ? Convert.toStr(m.get("dataItemId")) : key;
                taskDAO.addTaskData(task.getTaskNo(), atomicTask.getAtomicTaskNo(), key, message, 3600l, false);
            } else if (atomicTask.getGroupId() == OperationGroup.ConnectArmed.getId().intValue()
                    || atomicTask.getGroupId() == OperationGroup.Connect.getId().intValue()
                    || atomicTask.getGroupId() == OperationGroup.Disconnect.getId().intValue()
                    || atomicTask.getGroupId() == OperationGroup.CheckCdc.getId().intValue()) {
                Map<String, Object> m = JSONUtil.toBean(task.getParamJson(), Map.class);
                key = m.get("seq") != null ? Convert.toStr(m.get("seq")) : key;
                String stepOperationName = OperationName.forId(atomicTask.getOperationId()).getName();
                taskDAO.addTaskData(task.getTaskNo(), atomicTask.getAtomicTaskNo(), key, String.format("step %s failed, [%s]", stepOperationName, message), 3600l, false);

                //拉合闸失败日志
                if (atomicTask.getGroupId() != OperationGroup.CheckCdc.getId().intValue()) {
                    insertLogConnectDisConnectHis(task, atomicTask, LogConnectDisConnectHis.Result.failed.getCode(), message);
                }
            } else if (atomicTask.getGroupId() == OperationGroup.GetTou.getId().intValue()
                    || atomicTask.getGroupId() == OperationGroup.GetLoadLimit.getId().intValue()) {
                String stepOperationName = OperationName.forId(atomicTask.getOperationId()).getName();
                taskDAO.addTaskData(task.getTaskNo(), atomicTask.getAtomicTaskNo(), stepOperationName, String.format("step %s failed, [%s]", stepOperationName, message), 3600l, false);
            } else if (atomicTask.getGroupId() == OperationGroup.DcuGetBasicParam.getId().intValue()
                    || atomicTask.getGroupId() == OperationGroup.DcuGetNtpParam.getId().intValue()
                    || atomicTask.getGroupId() == OperationGroup.DcuGetCollScheme.getId().intValue()) {
                String stepOperationName = StepKeyUtil.getStepKey(atomicTask, task);
                taskDAO.addTaskData(task.getTaskNo(), atomicTask.getAtomicTaskNo(), stepOperationName, String.format("[%s]", message), 3600l, false);
            } else if (atomicTask.getGroupId() == OperationGroup.AlarmFilterGet.getId().intValue()) {
                AlarmFilterEnum alarmFilterEnum = AlarmFilterEnum.forId(atomicTask.getSeq() + 1);
                String stepOperationName = (alarmFilterEnum == null) ? key : alarmFilterEnum.getName();
                taskDAO.addTaskData(task.getTaskNo(), atomicTask.getAtomicTaskNo(), stepOperationName, String.format("[%s]", message), 3600l, false);
            }
        }

        // 返回给MDM,ESI随抄数据项接口失败的结果
        if (TaskType.Interface_ODR_Data.name().equals(task.getTaskType()) || TaskType.ESI_ODR_READ.name().equals(task.getTaskType())) {
            TaskResult taskResult = new TaskResult();
            taskResult.setTaskNo(task.getTaskNo());
            Map<String, Object> dataItemMap = JSONUtil.toBean(atomicTask.getAtomicTaskParam(), Map.class);
            Map<String, Object> taskMap = JSONUtil.toBean(task.getParamJson(), Map.class);
            Meter meter = assetService.getMeterById(task.getMeterId());
            taskMap.put("meterModelId", meter.getModelId());
            taskMap.putAll(dataItemMap);
            String messageId = null == taskMap.get("externalMessageId") ? task.getMessageId() : String.valueOf(taskMap.get("externalMessageId"));
            taskResult.setMessageId(messageId);
            taskResult.setExceptionCause(message);
            taskResult.setParamJson(JSONUtil.toJsonStr(taskMap));
            kafkaTemplate.send(TaskKafkaTopic.TASK_COMPLETE_RESULT_FROM_UTE_TO_ADAPTER, JSONUtil.toJsonStr(taskResult).getBytes(Charset.forName("utf-8")));
        }
        if (TaskType.ScheduleRead_Virtual_Profile.toString().equalsIgnoreCase(task.getTaskType()) || TaskType.MeterPlanCdc.toString().equalsIgnoreCase(task.getTaskType())) {
            logScheduleTaskDeviceService.sendMessage(task, LogScheduleTaskDevice.StatusEnum.Failed.getCode(), LogScheduleTaskDevice.StatusDescEnum.DecodeDataFailed.getCode());
        }
        return true;
    }

    private void readTaskExecutable(Task task, AtomicTask atomicTask, ComEntity terminal) throws UDISTaskExecutorException {
        if (OperationGroup.FirmwareImageActivate.getId() == atomicTask.getGroupId().intValue()) {
            firmwareTaskExecutable(task, atomicTask, terminal);
        }
    }

    //激活操作需要确认传输task已经完成
    private void firmwareTaskExecutable(Task task, AtomicTask atomicTask, ComEntity comEntity) throws UDISTaskExecutorException {
        Long deviceType = null;
        Long deviceId = null;
        if (task.getMeterId() != null) {
            deviceType = DeviceType.METER.getId();
            deviceId = task.getMeterId();
        } else {
            deviceType = comEntity.getComDeviceType();
            deviceId = comEntity.getDeviceId();
        }

        Long taskPid = Convert.toLong(getParameterMap(task, atomicTask).get("taskPid"));
        Long taskId = Convert.toLong(getParameterMap(task, atomicTask).get("taskId"));
        if (taskPid == null) {
            log.info("firmware upgrade activation taskPid not exists");
            assetManagementRemoteService.saveFwuReport(deviceId, deviceType, null, taskId, TemplateFwUpgrade.TaskType.ImageActivation.getCode(), LogFwUpgradeHis.UpgradeResult.failed.getCode(),
                    null, SystemClock.now() / 1000, "previous task not exists");
            return;
        }
        LogFwUpgradeHis transferReport = assetManagementRemoteService.getFwuReport(deviceId, deviceType, taskPid, TemplateFwUpgrade.TaskType.ImageTransfer.getCode());
        if (transferReport == null || transferReport.getUpgradeResult() != LogFwUpgradeHis.UpgradeResult.success.getCode()) {
            assetManagementRemoteService.saveFwuReport(deviceId, deviceType, null, taskId, TemplateFwUpgrade.TaskType.ImageActivation.getCode(), LogFwUpgradeHis.UpgradeResult.failed.getCode(),
                    null, SystemClock.now() / 1000, "previous task failed");
            throw new UDISTaskExecutorException(TaskExecuteErrorCode.FW_UP_NOT_COMPLETE.toString());
        }
    }

    private Boolean isReadFromTerminal(Task task, AtomicTask atomicTask) {
        if (task.getMeterId() == null) {
            return true;
        }

        if (OperationGroup.DCUGetMeterList.getId().longValue() == atomicTask.getGroupId()) {
            return true;
        }
        return false;
    }

    /**
     * 需要特殊处理的结果，返回对应的handler, 否则返回null
     *
     * @param dataItemDto
     * @param atomicTask
     * @return
     */
    private Class getHandlerClass(DataItemDTO dataItemDto, AtomicTask atomicTask) throws UDISTaskExecutorException {
        Class cla = null;
        log.debug("OperationGroup={}", OperationGroup.forId(atomicTask.getGroupId().intValue()));
        switch (OperationGroup.forId(atomicTask.getGroupId().intValue())) {
            //随抄数据项
            case ReadRegister:
                cla = registerHandlerClass(dataItemDto);
                break;
            case ODRReadProfiles:
            case ScheduleReadProfiles:
            case DCUSetMeterList:
            case DCUGetMeterList:
                break;
            case FirmwareImageTransfer:
            case FirmwareImageActivate:
                cla = firmwareReadHandler(atomicTask);
                break;
            case FirmwareVersionRead:
                cla = ReadFirmwareVersionHandler.class;
                break;
            case FirmwareVersionVerify:
                cla = ReadFirmwareVersionConfirmHandler.class;
                break;
            case Disconnect:
                cla = ReadControlStateHandler.class;
                break;
            case Connect:
            case ConnectArmed:
                cla = getConnectArmedHandler(atomicTask);
                break;
            case CheckCdc:
                cla = ReadControlStateHandler.class;
                break;
            case DcuGetCollScheme:
            case DcuSetCollScheme:
                cla = getDcuCollSchemeHanler(atomicTask);
                break;
            case DcuGetNtpParam:
                cla = getDcuNtpParamHandler(atomicTask);
                break;
            case DcuGetBasicParam:
                cla = getDcuBasicParamHandler(atomicTask);
                break;
            case GetTou:
                cla = getTouHandler(atomicTask);
                break;
            case GetLoadLimit:
                cla = getLoadLimitHandler(atomicTask);
                break;
            case AlarmFilterGet:
                cla = ReadAlarmHandler.class;
                break;
            case PlcOnlineList:
                cla = PlcOnlineListHandler.class;
                break;
            case GetClock:
                cla = ReadClockObjectHandler.class;
                break;
            case StepTariffActiveRatePriceGet:
            case StepTariffActiveStepGet:
            case StepTariffActiveDateGet:
            case StPaymentControlConfigGet:
            case StepTariffBackUpRatePriceGet:
            case StepTariffBackUpStepGet:
            case StFunctionControlConfigGet:
                cla = ReadStepTariffHandler.class;
                break;
            case GetDisplay:
                cla = ReadDisplayCodeHandler.class;
                break;
            default:
                throw new UDISTaskExecutorException(TaskExecuteErrorCode.UNEXPECTED_VALUE.toString() + atomicTask.getGroupId().intValue());
        }
        return cla;
    }

    private Class firmwareReadHandler(AtomicTask atomicTask) {
        OperationName operationName = OperationName.forId(atomicTask.getOperationId());
        switch (operationName) {
            case GetImageTransferStatus:
                return ReadFirmwareTransferredStatusHandler.class;
            case GetImageNotTransferLastBlock:
                return ReadFirstNotTransferredBlockHandler.class;
            case GetFwImageBlockSize:
                return ReadFirmwareBlockSizeHandler.class;
            case GetImagesToActivate:
                return ReadImagesToActivateHandler.class;
            default:
                return null;
        }


    }

    private Class registerHandlerClass(DataItemDTO dataItemDto) {
        if (dataItemDto instanceof DLMSSubDataItemDTO) {
            DLMSSubDataItemDTO dlmsSubDataItemDTO = (DLMSSubDataItemDTO) dataItemDto;
            if (dlmsSubDataItemDTO.getClassId() == ObjectType.REGISTER.getValue() || dlmsSubDataItemDTO.getClassId() == ObjectType.EXTENDED_REGISTER.getValue()) {
                //scaler_unit
                if (dlmsSubDataItemDTO.getAttributeId() == 3) {
                    return ReadScalerUnitHandler.class;
                }
            }
        }
        return null;
    }

    private Class getConnectArmedHandler(AtomicTask atomicTask) {
        OperationName operationName = OperationName.forId(atomicTask.getOperationId());
        switch (operationName) {
            case GetControlMode:
                return ReadControlModeHandler.class;
            case GetControlState:
                return ReadControlStateHandler.class;
            default:
                return null;
        }
    }


    private Class getDcuCollSchemeHanler(AtomicTask atomicTask) {
        OperationName operationName = OperationName.forId(atomicTask.getOperationId());
        switch (operationName) {
            case GetDcuCollScheme:
                return ReadDcuCollSchemeHandler.class;
            case GetDcuMeterTask:
                return ReadDcuMeterTaskHandler.class;
            default:
                return null;
        }
    }

    private Class getDcuBasicParamHandler(AtomicTask atomicTask) {
        OperationName operationName = OperationName.forId(atomicTask.getOperationId());
        switch (operationName) {
            case GetDcuClockOverThreshold:
            case GetDcuMonthOverThreshold:
            case GetDcuBroadcastTimeCheck:
            case GetDcuDeviceName:
            case GetDcuCommunicationAddr:
            case GetDcuSignalStrength:
            case GetDcuLpDensity:
            case GetDcuGPRSParam:
            case GetDcuEthernetParam:
            case GetDcuBasicComParam:
            case FtpParametersGet:
            case GetGprsModemApn:
            case GetDcuAutoConnect:
            case GetHeartBeatCycle:
            case GetAutoRegisterMode:
            case GetRefreshMeterStatus:
            case GetNetworkOnlineMeterList:
            case GetNetWorkTopologyInformation:
            case GetDcuPushStatus:
                return ReadDcuSimpleDataHandler.class;
            default:
                return null;
        }
    }

    private Class getDcuNtpParamHandler(AtomicTask atomicTask) {
        OperationName operationName = OperationName.forId(atomicTask.getOperationId());
        switch (operationName) {
            case GetNtpActivated:
            case GetNtpServerAddr:
            case GetNtpServerPort:
                return ReadDcuSimpleDataHandler.class;
            default:
                return null;
        }
    }

    private Class getTouHandler(AtomicTask atomicTask) {
        OperationName operationName = OperationName.forId(atomicTask.getOperationId());
        switch (operationName) {
            case GetCalendarNameActive:
            case GetDayProfileActive:
            case GetWeekProfileActive:
            case GetSeasonProfileActive:
            case GetCalendarNamePassive:
            case GetDayProfilePassive:
            case GetWeekProfilePassive:
            case GetSeasonProfilePassive:
            case GetActivateCalendarTime:
            case GetSpecialDays:
            case GetFriendlyDays:
                return ReadActiveCalendarHandler.class;
            default:
                return null;
        }
    }

    private Class getLoadLimitHandler(AtomicTask atomicTask) {
        OperationName operationName = OperationName.forId(atomicTask.getOperationId());
        switch (operationName) {
            case GetMonitorValue:
            case GetThresholdNormal:
            case GetThresholdEmergency:
            case GetMinOverThresholdDuration:
            case GetMinUnderThresholdDuration:
            case GetEmergencyProfile:
            case GetEmergencyProfileGroupIDList:
            case GetLoadLimitActions:
                return ReadLimiterHandler.class;
            default:
                return null;
        }
    }

    public void insertLogConnectDisConnectHis(Task task, AtomicTask atomicTask, Integer result, String reason) {
        Map<String, Object> paramMap = this.getParameterMap(task, atomicTask);
        Integer source = MapUtil.get(paramMap, "source", Integer.class);
        Long tvRequest = MapUtil.get(paramMap, "tvRequest", Long.class);
        Long tvExecute = MapUtil.get(paramMap, "tvExecute", Long.class);
        Integer operate = MapUtil.get(paramMap, "operate", Integer.class);
        String operator = MapUtil.get(paramMap, "operator", String.class);

        source = source == null ? LogConnectDisConnectHis.Source.MDM.getCode() : source;
        LogConnectDisConnectHis logConnectDisConnectHis = new LogConnectDisConnectHis();
        logConnectDisConnectHis.setDeviceId(task.getMeterId());
        logConnectDisConnectHis.setSource(source);
        logConnectDisConnectHis.setResult(result);
        logConnectDisConnectHis.setReason(reason);
        logConnectDisConnectHis.setOperate(operate);
        logConnectDisConnectHis.setOperator(operator);
        logConnectDisConnectHis.setTvRequest((tvRequest == null || tvRequest == 0) ? System.currentTimeMillis() / 1000 : tvRequest);
        logConnectDisConnectHis.setTvExecution((tvExecute == null || tvExecute == 0) ? System.currentTimeMillis() / 1000 : tvExecute);
        logConnectDisConnectHis.setMessageId(task.getMessageId());
        logConnectDisConnectHisMapper.insert(logConnectDisConnectHis);
    }

}
